package com.hearsilent.discreteslider.libs;

import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

/**
 * @author Almer Thie (code.almeros.com)
 * Copyright (c) 2013, Almer Thie (code.almeros.com)
 * <p>
 * All rights reserved.
 * <p>
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 * <p>
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the distribution.
 * <p>
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 */
public abstract class BaseGestureDetector {

	protected final Context mContext;
	protected boolean mGestureInProgress;

	protected TouchEvent mPrevEvent;
	protected TouchEvent mCurrEvent;

	protected float mCurrPressure;
	protected float mPrevPressure;
	protected long mTimeDelta;

	/**
	 * This value is the threshold ratio between the previous combined pressure
	 * and the current combined pressure. When pressure decreases rapidly
	 * between events the position values can often be imprecise, as it usually
	 * indicates that the user is in the process of lifting a pointer off of the
	 * device. This value was tuned experimentally.
	 */
	protected static final float PRESSURE_THRESHOLD = 0.67f;

	public BaseGestureDetector(Context context) {
		mContext = context;
	}

	/**
	 * All gesture detectors need to be called through this method to be able to
	 * detect gestures. This method delegates work to handler methods
	 * (handleStartProgressEvent, handleInProgressEvent) implemented in
	 * extending classes.
	 *
	 * @param event event
	 * @return boolean
	 */
	public boolean onTouchEvent(TouchEvent event) {
		//final int actionCode = event.getAction() & MotionEvent.ACTION_MASK;
		final int actionCode = event.getAction();
		if (!mGestureInProgress) {
			handleStartProgressEvent(actionCode, event);
		} else {
			handleInProgressEvent(actionCode, event);
		}
		return true;
	}

	/**
	 * Called when the current event occurred when NO gesture is in progress
	 * yet. The handling in this implementation may set the gesture in progress
	 * (via mGestureInProgress) or out of progress
	 *
	 * @param actionCode
	 * @param event
	 */
	protected abstract void handleStartProgressEvent(int actionCode, TouchEvent event);

	/**
	 * Called when the current event occurred when a gesture IS in progress. The
	 * handling in this implementation may set the gesture out of progress (via
	 * mGestureInProgress).
	 *
	 * @param actionCode
	 * @param event
	 */
	protected abstract void handleInProgressEvent(int actionCode, TouchEvent event);

	protected void updateStateByEvent(TouchEvent curr) {
		final TouchEvent prev = mPrevEvent;

		if (mCurrEvent != null) {
			mCurrEvent = null;
		}

		mTimeDelta = curr.getOccurredTime() - prev.getOccurredTime();

		mCurrPressure = curr.getPointerScreenPosition(curr.getIndex()).getX();
		mPrevPressure = prev.getPointerScreenPosition(prev.getIndex()).getX();
		float x = curr.getPointerScreenPosition(curr.getIndex()).getX();
		float y = curr.getPointerScreenPosition(curr.getIndex()).getY();

	}

	protected void resetState() {
		if (mPrevEvent != null) {
			mPrevEvent = null;
		}
		if (mCurrEvent != null) {
			mCurrEvent = null;
		}
		mGestureInProgress = false;
	}

	/**
	 * Returns {@code true} if a gesture is currently in progress.
	 *
	 * @return {@code true} if a gesture is currently in progress, {@code false} otherwise.
	 */
	public boolean isInProgress() {
		return mGestureInProgress;
	}

	/**
	 * Return the time difference in milliseconds between the previous accepted
	 * GestureDetector event and the current GestureDetector event.
	 *
	 * @return Time difference since the last move event in milliseconds.
	 */
	public long getTimeDelta() {
		return mTimeDelta;
	}

	/**
	 * Return the event time of the current GestureDetector event being
	 * processed.
	 *
	 * @return Current GestureDetector event time in milliseconds.
	 */
	public long getEventTime() {
		return mCurrEvent.getOccurredTime();
	}

}